AWS CDK+Serverlessのアーキテクチャパターンの実装が勢揃い!CDK Patternsの紹介
はじめに
CX事業本部の佐藤智樹です。
今回はAWS CDKでServerlessアーキテクチャを構築する上で参考となる実装が紹介されているCDK Patternsという取り組みが気になったので紹介します。
実装はGitHub上で公開されているので、いつでもすぐにcloneして動かすことができます。
この記事を読むことでAWS CDK+Serverlessで何か開発する際の設計パターンが分かり、独自に検討するより早く実装できるようになります。
正直自分でもこのパターンいいじゃん!使いたい!となったので、CDKで何か作ってる方には絶対参考になると思います。
CDK Patternsとは
以下はCDK PatternsのGitHubリポジトリからの引用です。
CDK Patterns houses an opensource collection of AWS Serverless architecture patterns built with CDK for developers to use. The patterns are sourced via AWS Heroes / Advocates and come with links to their original content
AWS HeroesやAdvocatesによって紹介されたパターンの引用と実装パターンが併記されています。
パターンの紹介はGitHubだけでなく専用のサイトも構築されており、そちらから各AWSサービスに関連するパターンから調べることもできます。
執筆時点(2020/10/05時点)ではGitHub上で以下のパターンが確認できます。
Polly パターン
Amazon PollyとLambdaやAPI Gatewayと統合するパターンです。API Gateway経由でテキストを受信して音声情報をリクエスト元に返却します。
Amazon Translateとも統合しているので、別の言語に翻訳して音声を返却することもできます。Amazon PollyやAmazon Translateの構成をCDKで管理したい場合やAPI経由で簡単に上記のサービスを使ってみたい場合に参考になるパターンです。
s3-angular/react-website パターン
AngularかReactを使ってAmazon S3にサイトをデプロイするパターンです。
cdk-spa-deployコマンドを使用してWebサイトをS3にホスティングすることができます。
※注意:Route53やCloudFrontの設定は行われないためその部分は追加で実施する必要があります。
Basic MQ パターン
AmazonMQを使用して静的カスタムドメインエンドポイントをデプロイするためのパターンです。
クライアントとブローカー間における、安全でスケーラブルなエンドツーエンドのSSL暗号化メッセージング通信が行えます。(Serverlessなのか?)
The Big Fan パターン
API Gatewayに来たリクエストをAmazon SNSで出力先を分けてからSQSに格納してLambdaで処理するパターンです。
Statusごとに処理することで全ての処理がSQSで詰まってしまうことを防止したり、別のサービスに処理を投げたりと拡張性が増します。詳しいことは以下の記事のメリット部分などで言及されています。
CloudWatch Dashboard
CloudWatch DashboardをCDKで作成するためのサンプルが紹介されています。
具体的には、API Gatewayが4XX、5XXを返した場合やDynamoDBのキャパシティユニット枯渇によるスロットリングが発生している場合の閾値、アラーム設定、ダッシュボード作成が含まれています。このサンプルを参考にすることで、CDKでダッシュボードを作成する方法を簡単に確認することができます。
The Destined Lambda パターン
EventBridgeの前にLambdaを配置してから処理をEventBridgeで振り分けるパターンです。
Lambdaを前段に置くことでEventBridgeと接続するために必要な固有の実装をDestined Lambdaに集約することができます。
またStep Functionsを使うほどではないが少し複雑なことがしたい場合に使えます。例えば処理を分岐させることでLambdaごとの処理を単純にしたり、EventBridgeで成功/失敗に応じて他のAWSサービスにイベントを送ったりすることができます。
The Dynamo Streamer パターン
API GatewayからDynamoDBにイベントを送信して、DynamoDB StreamでLambdaを実行するパターンです。
基本的なAPI Gateway->Lambda->DynamoDBで書き込むパターンでも同じ処理はできますが、異常が発生した場合にDLQに処理を送ったりしなければイベントが消失してしまいます。そこでDynamoDBにイベントを一度格納することで、イベントの消失を防ぐことができます。
参考URLの本筋とは外れますが、API Gateway->DynamoDBの実装パターンなのでLambdaレスサーバーレスをCDKでやりたい場合にも参考になるかと思います。
The EFS Lambda パターン
LambdaからEFSにアクセスしてファイルのデータをGET、POST、DELETEするパターンです。
S3を使う場合と比べると、大量のデータをLambdaでロードしたい(機械学習のモデルなど)場合に/tmp領域が512MBまでとなる制限を回避して処理することができます。その他の利点などは以下の記事でまとまっています。
The EventBridge ATM パターン
Lambdaから来たイベントをEventBridgeのRuleに基づいて振り分けるパターンです。例としてATMシステムが実装されています。
イベントのルーティングを集中して管理できるので、マイクロサービス間でイベントを送受信する窓口が分かりやすくなります。
The EventBridge Circuit Breaker パターン
LambdaのエラーをEventBridgeに送信して処理することでサーキットブレーカーを実装するパターンです。以下の図はクローズされるまでの流れを表しています。
The EventBridge Circuit Breaker パターン
LambdaがExternal ServiceのAPIなどを利用していて、External Serviceがダウンしてしまった場合に、エラーイベントをEventBridgeに投げておきます。エラーが閾値以上になった場合は、LambdaからExternal Serviceへのアクセスを停止し、リクエスト元へ即座にエラーを返すようになっています。
上記により、LambdaがExternal Serviceを無駄に呼び出す実行時間分の料金を節約したりすることができます。また即座にエラーが返るのでエンドユーザも必要以上にエラーを待つ必要がなくなります。
The EventBridge ETL パターン
S3からデータをロードしてEventBridgeで処理をLambdaに振り分けてETLを実行するパターンです。大きめのデータのロードを想定して、S3からのデータロードにはFargateが使われています。
(注意:本番で使用する場合は、SQSによるエラー時の復元処理やKMSによる暗号化を考慮してください)
自分個人としてETLを使用したことがないので深いことは書けないのですがAWS GlueなどETLサービスと比べると細かいチューニングはできるので既存のサービスが要件を満たさない場合は使用しても良いかもしれないです。
The Lambda Power Tuner
SAR(Serverless Application Repository)のaws-lambda-powertuningツールを作成して、Lambdaの性能をチューニングできる実装です。
チューニングツールを使うことでLambdaの実装に対してどのメモリ容量が一番コストパフォーマンスが高いか確認することができます。ツールの詳細や使用方法は以下の記事などでも確認できます。
またSARのデプロイをCDKに組み込むことで色々なテンプレートにAWSリソースの記述が分散するのを防ぐことができます。
The Lambda Trilogy
以下に記載した3つのLambdaのパターンが実装されています。
- The Single Purpose Lambda(1つの目的ごとに独立したソースで構成するパターン)
- The Fat Lambda(複数の目的の処理を1つのソースでまとめて実装するパターン)
- The Lambda-lith(Expressなどを使って1つのLambdaで処理を振り分けるパターン)
リンク先の中でそれぞれの実装の利点と欠点が語られているので、今までLambdaの実装を行ってきた方にも参考になるかと思います。
個人的にはサーバーレスアーキテクチャばかり触っているとThe Single Purpose Lambdaが最も良いと思ってました。ただ将来的にサーバーレスが廃れてしまうことを考慮した場合は、別のパターンも有りかと少しだけ思いました。
The RDS Proxy
LambdaからRDS Proxy経由でRDSのテーブル作成、データ挿入、データ抽出を実行する実装です。
RDSを起動するためのVPC、セキュリティグループの作成など事前準備も実装に含まれているので、RDS Proxyをとりあえず試してみたい方におすすめです。
The Saga Step Function
マイクロサービスのSagaパターンをStepFunctionsで実装したものです。複数のLambdaなどにまたがる一連の処理が途中で失敗した場合、処理を打ち消すように補償トランザクションを実行します。
Sagaパターンの詳細な情報は以下の記事やマイクロサービスの本などで紹介されています。
The Scalable Webhook
API Gateway+Lambda+SQSなどを用いてスケーラブルなWebhookを作るパターンです。
RDSに書き込む量を制限するために、中間の処理を挟んでいます。現在ならRDS Proxyを使うことでも解決できます。 ※ソース自体は簡略化のためにRDSをDynamoDBで代替えされています。
The Simple GraphQL Service
CDKからAppSyncを使ってGraphQLを実装するパターンです。
実装は現在StableなL1コンストラクトが使われています。まだExperimental VersionですがL2コンストラクトを使いたい場合はこちらの記事が役に立つと思います。
The Simple Webservice
シンプルにAPI Gateway->Lambda->DynamoDBでAPIを実行時にDynamoDBを更新する構成です。
初めて実装する時はこのようなパターンから始めるのが良いかと思います。手動でWebコンソールから作成する場合と比べてロールなどが自動生成されるので簡単に始めることができます。
The State Machine
CDKでStepFunctionsを使っている設計です。
内容は基本的ですが、CDKでStepFunctionsを使う時の快適さが伝わりやすいと思うので、StepFunctionsを最初に触る際に使ってみるのが良いかと思います。
The X-Ray Tracer
DynamoDB、SQS、SNSなどとLambdaを繋ぐ際にX-Rayでトレースする方法がわかる実装です。
ReadMeに詳しく動作確認する際の挙動などが書かれているので、X-Rayを導入する前に何ができるのか調査するために簡単に利用することができます。
所感
今後CDKが発展していく中で、このような基本パターンの実装は様々な会社や個人で行われることになります。
今回紹介したパターンを知っていることで、少しでも設計と実装の手間を減らせれば幸いです。
コントリビュートも歓迎されているようなので、時間ができたら自分も提案してPRを送りたいと思います。